/*
 * SlamTec Base Ref Design
 * Copyright 2009 - 2015 RoboPeak
 * Copyright 2013 - 2015 Shanghai SlamTec Co., Ltd.
 * http://www.slamtec.com
 * All rights reserved.
 */
/*
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "common/common.h"
#include "battery.h"
#include "beep.h"
#include "utils/filters.h"
#include "drv/serial_channel.h"
#include "string.h"
#define CONFIG_POWERSTATE_CHECK_DURATION       10       //单位：ms
#define CONFIG_CHARGEBASE_REMOVAL_THRESHOLDTS  100      //单位：ms
// #define USE_DC_STATSUS                                  //目前只有一个充电检测，需要选择一个（DC口/充电桩）
static _u8	_queryBatteryElectricityPercentageBuff[4]={0xff,0x01,0x0d,0x0d};//查询电池电量百分比
static _u8	_queryBatteryChargingStateBuff[4]={0xff,0x01,0x16,0x16};//查询电池状态
_u8	_queryBatteryStatusType=0;
static _u32 batteryFrequency = 0;
static _u32 batteryElectricityPercentage = 0;
//static _u8 chargeSound = 2;
static _u8 isChargeInserted = 0;
//static _u8 chargeInsertedTs = 0;
static _u8 isDcInserted = 0;
//static _u8 dcInsertedTs = 0;

#define BATTERY_VOLTAGE_SAMPLE_CHANNEL        6
#define BATTERY_VOLTAGE_SAMPLE_ADC_ID         1
// the voltage scale factor to transform the voltage on the ADC pin to the actual battery voltage
// it is controlled by the resistor network, please refer to the ref design schematic for details
#define BATTERY_VOLTAGE_SCALEFACTOR           11.20
// #define BATTERY_VOLTAGE_FULL                  ((int)(16.8 * 1000)) //mV
// #define BATTERY_VOLTAGE_EMPTY                 ((int)(12.0 * 1000)) //mV

#define BATTERY_VOLTAGE_FULL                  ((int)(28.0 * 1000)) //mV 我们使用的是24v电池
#define BATTERY_VOLTAGE_EMPTY                 ((int)(23.0 * 1000)) //mV

// avg filter queue for power supply sampling...
#define PWR_FILTER_QUEUE_BIT    3
#define PWR_FILTER_QUEUE_SIZE   (0x1<<PWR_FILTER_QUEUE_BIT)
static _u16 _pwrCachedBattVoltADCVal = 0;
static _u16 _pwrFilterBattVoltQueue[PWR_FILTER_QUEUE_SIZE+2];
static _u8  _pwrFilterPos;
enum {
    BATTERY_ADC_STATE_IDLE = 0,
    BATTERY_ADC_STATE_WAITING = 1,
};
static _u8  _pwrAdcSampleState = 0;
static void _battery_sample_batteryvoltage();
/*
 * 电池容量ADC检测初始化函数
 */
static void init_electricity_detect(void)
{
    _pwrAdcSampleState = BATTERY_ADC_STATE_IDLE;
    _pwrFilterPos = 0;
    // preheat the adc avg-filter queue...
    do{
          _battery_sample_batteryvoltage();
      } while (_pwrFilterPos!=0);
}
void QueryBatteryStatus(u8 _ucBatteryStatusType)
{//Modify by LAY

	
	switch(_ucBatteryStatusType)
	{
		case 0:
				Usart_Write(UART4,_queryBatteryChargingStateBuff,4);
				_queryBatteryStatusType++;
			break;
		case 1:
				Usart_Write(UART4,_queryBatteryElectricityPercentageBuff,4);
				_queryBatteryStatusType=0;
			break;
	default:
				_queryBatteryStatusType=0;
				break;
		
	}

}
/*
 * 获取电池电压函数
 * 返回电压值，单位：mV
 */
_u32 get_electricity(void)
{
    const _u32  ADC_LEVELS = (0x1<<ADC_RES_BIT); //4096
  //  ADC_REF = 2.495
  //  VBATT / BATTERY_VOLTAGE_SCALEFACTOR = adc_val * ADC_REF / 4096
  const float ADC_TO_BATT_VOLT_FACTOR = (ADC_REF_VOLT * 1000 * BATTERY_VOLTAGE_SCALEFACTOR) / ADC_LEVELS;
  const _u32  ADC_TO_BATT_VOLT_FACTOR_fixQ10 = (_u32)(ADC_TO_BATT_VOLT_FACTOR * 1024.0);
  return (_pwrCachedBattVoltADCVal * ADC_TO_BATT_VOLT_FACTOR_fixQ10)>>10;
	

}
/*
 * 获取电池容量百分比函数
 * 返回百分比0-100%
 */
_u8 get_electricitypercentage(void)
{
    return batteryElectricityPercentage;
}
/*
 * 电池充电电平检测初始化函数
 */
static void init_charge_detect(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
    GPIO_InitStructure.GPIO_Pin = BATT_FAULT | BATT_CHRG | BATT_TOC | BATT_READY;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    // GPIO_InitStructure.GPIO_Pin = HOCHARGE_DETECT | DCCHARGE_DETECT;
    // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
    // GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*
 * 电池充电状态检测函数
 * 返回正在充电或不在充电状态
 */
_u8 charge_detect_getstatus(void)
{
//    if ((isChargeInserted || isDcInserted) && (0 == GPIO_ReadInputDataBit(GPIOE, BATT_READY))) {//modify by LAY
    if ((isChargeInserted || isDcInserted)) {
        return ISCHARGE_CHRG;
    } else {
        return ISCHARGE_NOCHRG;
    }
}
/*
 * 获取电池DC电源插头充电状态函数
 */
_s8 get_dc_charge_status(void)
{
    return isDcInserted;
}
/*
 * 获取电池充电桩充电状态函数
 */
_s8 get_home_charge_status(void)
{
    return isChargeInserted;
}
static void _on_battery_adc_data_ready(_u16 adcData)
{
    _pwrCachedBattVoltADCVal = add_to_avg_filter_u16(adcData, _pwrFilterBattVoltQueue, _pwrFilterPos, PWR_FILTER_QUEUE_SIZE);
    if ( (++_pwrFilterPos) >= PWR_FILTER_QUEUE_SIZE) {
        _pwrFilterPos = 0;
    }
}

static void _battery_sample_batteryvoltage()
{
    switch (_pwrAdcSampleState) {
    case BATTERY_ADC_STATE_IDLE:
        adc_read_start(GET_ADC(BATTERY_VOLTAGE_SAMPLE_ADC_ID), BATTERY_VOLTAGE_SAMPLE_CHANNEL);
        _pwrAdcSampleState = BATTERY_ADC_STATE_WAITING;
        break;
    case BATTERY_ADC_STATE_WAITING:
        if (adc_read_is_ready(GET_ADC(BATTERY_VOLTAGE_SAMPLE_ADC_ID))) {
            _on_battery_adc_data_ready(adc_read_final(GET_ADC(BATTERY_VOLTAGE_SAMPLE_ADC_ID)));
            _pwrAdcSampleState = BATTERY_ADC_STATE_IDLE;
        }
        break;
    }
}
/*
 * 电池相关初始化函数
 * 初始化电池容量检测
 * 初始化电池充电检测
 */
void init_battery(void)
{
    init_electricity_detect();
    init_charge_detect();
}
/*
 * 电池相关模块函数
 * 充电状态的判定等
 */
void heartbeat_battery(void)
{
//    _battery_sample_batteryvoltage();
    if ((getms() - batteryFrequency) >= 50) {
        //3秒检测一次电池容量及计算百分比
        batteryFrequency = getms();
				/*数据解析*/
		if(Uart4_ReceiveTemp[0]==0xff)//帧头检测
		{
			if(Uart4_ReceiveTemp[2]==0x0D)//电量百分比 
			{
				batteryElectricityPercentage = Uart4_ReceiveTemp[3];
			}
			else if(Uart4_ReceiveTemp[2]==0x16)//电池状态
			{	
				if(Uart4_ReceiveTemp[3]==0x00)//故障
				{
                    #if defined USE_DC_STATSUS
                    isDcInserted=0;
                    #else
                    isChargeInserted = 0;
                    #endif
				}
				else if(Uart4_ReceiveTemp[3]==0x01)//充电中
				{
                    #if defined USE_DC_STATSUS
                    isDcInserted=1;
                    #else
                    isChargeInserted = 1;
                    #endif
				}
				else if(Uart4_ReceiveTemp[3]==0x02)//放电中
				{
                    #if defined USE_DC_STATSUS
                    isDcInserted=0;
                    #else
                    isChargeInserted = 0;
                    #endif
				}
				else if(Uart4_ReceiveTemp[3]==0x04)//电池闲置
				{
                    #if defined USE_DC_STATSUS
                    isDcInserted=0;
                    #else
                    isChargeInserted = 0;
                    #endif

                    if(batteryElectricityPercentage == 0x64)
                    {
                        isChargeInserted=1;
                    }
				}
				else if(Uart4_ReceiveTemp[3]==0x08)//未连接电池
				{
                    #if defined USE_DC_STATSUS
                    isDcInserted=0;
                    #else
                    isChargeInserted = 0;
                    #endif
				}
				else;
				
			}
			else;
		
		}
		else;

		memset(Uart4_ReceiveTemp,0,Uart4BuffSize);//缓存清空
		Uart4RevCount=0;//计数清0
		/*电池状态查询*/
		QueryBatteryStatus(_queryBatteryStatusType);
				
/*        _u32 currentVolt = get_electricity();
        // DBG_OUT("currentVolt = %d\r\n", currentVolt);
        if (currentVolt < BATTERY_VOLTAGE_EMPTY) {
            batteryElectricityPercentage = 0;
        } else if (currentVolt > BATTERY_VOLTAGE_FULL) {
            batteryElectricityPercentage = 100;
        } else {
            batteryElectricityPercentage = (currentVolt - BATTERY_VOLTAGE_EMPTY)*100 / (BATTERY_VOLTAGE_FULL - BATTERY_VOLTAGE_EMPTY);
        }

        if (batteryElectricityPercentage < 25 && ISCHARGE_CHRG != charge_detect_getstatus()) {
            {

//                beep_beeper(3000, 400, chargeSound);
                if ((chargeSound += 1) >= 250) {
                    chargeSound = 250;
                }
            }
        } else {
            chargeSound = 2;
        }
    }
//     if (isChargeInserted) {
//         //是否处在充电桩充电状态
//         if (!PIN_READ(GPIOB, HOCHARGE_DETECT)) {
//             //在充电桩充电下：检测是否脱离充电桩，拔出则更改充电桩充电状态
//             if (getms() - chargeInsertedTs >= CONFIG_CHARGEBASE_REMOVAL_THRESHOLDTS) {
// //                beep_beeper(5000, 80, 2);
//                 isChargeInserted = 0;
//             }
//         } else {
//             chargeInsertedTs = getms();
//         }

//     } else {
//         //不在充电桩充电下：检测是否脱离充电桩，插入则更改充电桩充电状态
//         if (PIN_READ(GPIOB, HOCHARGE_DETECT)) {
//             isChargeInserted = 1;
// //            beep_beeper(5000, 80, 2);
//             chargeInsertedTs = getms();
//         }

//     }
    if (isDcInserted) {
        //是否处在DC电源充电状态
        if(!PIN_READ(GPIOB, DCCHARGE_DETECT)) 
				{
            //在DC电源充电下：检测是否拔出DC电源，拔出则更改DC电源充电状态
            if (getms() - dcInsertedTs >= CONFIG_CHARGEBASE_REMOVAL_THRESHOLDTS * 2) 
						{
                //防抖动
                isDcInserted = 0;
            }
        } 
				else 
				{
            dcInsertedTs = getms();
        }

    } 
		else 
		{
        //不在DC电源充电下：检测DC电源是否插入，插入则更改DC电源充电状态
        if (PIN_READ(GPIOB, DCCHARGE_DETECT)) 
				{
            isDcInserted = 1;
            dcInsertedTs = getms();
        }
    }*/
	}
}
